home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 142
/
Gekkan Dennou Club - 2000.3 Vol. 142 (Japan).7z
/
Gekkan Dennou Club - 2000.3 Vol. 142 (Japan) (Track 1).bin
/
tools
/
s44play
/
s44p101s.lzh
/
file.s
< prev
next >
Wrap
Text File
|
2000-01-24
|
25KB
|
1,159 lines
.include doscall.mac
.include dosconst.equ
.include global.mac
;----------------------------------------------------------------
;ファイルをオープンする
;<current_param_ptr.l:パラメータバッファのアドレス
;>next_param_ptr.l:次のパラメータバッファのアドレス
;>d0.l:負数=エラー,0=データなし正常終了,その他=データあり
;>n-flag:mi=エラー
;>z-flag:eq=データなし正常終了
.text
.align 4,$2048
open_file::
movem.l d1-d7/a0-a6,-(sp)
movea.l current_param_ptr,a2
lea.l (pb_size,a2),a0
move.l a0,next_param_ptr
lea.l filename_buffer,a4
tst.b (pb_files,a2)
bne 20f ;ワイルドカード検索中
movea.l a4,a0 ;ファイル名のバッファ
movea.l (pb_ptr,a2),a1 ;ファイル名
bsr fullpath ;フルパスにする
adda.l d0,a0 ;主ファイル名の先頭
move.l a0,filename_nameptr
moveq.l #'?',d0
bsr strchr
bpl 10f ;ワイルドカードあり
moveq.l #'*',d0
bsr strchr
bpl 10f ;ワイルドカードあり
;ワイルドカードなし
movea.l a4,a0
cmpi.b #'-',(a0)+
bne 40f ;ワイルドカードなし,標準入力ではない
tst.b (a0)
bne 40f ;ワイルドカードなし,標準入力ではない
;ワイルドカードなし,標準入力
clr.w fileno ;標準入力
bra 50f
;ワイルドカードあり
10: lea.l files_buffer,a5
move.w #$20,-(sp) ;ファイルを検索
move.l a4,-(sp) ;フルパスでワイルドカードを含むファイル名
move.l a5,-(sp) ;_FILESのバッファ
DOS _FILES
lea.l (10,sp),sp
tst.l d0
bmi 80f ;ファイルが見つからない
st.b (pb_files,a2)
bra 30f
;ワイルドカード検索中
20: lea.l files_buffer,a5
move.l a5,-(sp) ;_FILESのバッファ
DOS _NFILES
addq.l #4,sp
tst.l d0
bpl 30f
sf.b (pb_files,a2)
sf.b (pb_is_cdxa,a2)
bra 90f ;ワイルドカード検索終わり
;ワイルドカードに該当するファイルが見つかった
30: movea.l filename_nameptr,a0
lea.l (fiName,a5),a1
bsr strcpy
move.l a2,next_param_ptr
;ワイルドカードなし,標準入力ではない
40: clr.w -(sp)
move.l a4,-(sp)
DOS _OPEN
addq.l #6,sp
tst.l d0
bmi 80f ;ファイルが見つからない
move.w d0,fileno
50: move.w #2,-(sp)
clr.l -(sp)
move.w fileno,-(sp)
DOS _SEEK
move.l d0,d4 ;データのサイズ
clr.w (6,sp)
DOS _SEEK
addq.l #8,sp
move.l current_file_frequency,d2 ;サンプリング周波数の指定
;フォーマットの指定があるときは,
;サンプリング周波数の指定もあるはず
move.w current_file_format,d6 ;フォーマットの指定
bpl 20f ;フォーマット指定済み
move.l a4,d0
beq 10f ;標準入力なので拡張子を得られない
moveq.l #'.',d0
movea.l a4,a0
bsr strrchr
bmi 10f ;'.'がない
adda.l d0,a0 ;最後の'.'の位置
;拡張子.m??と.s??と.p16
moveq.l #MS16B,d6
lea.l (str_dot_mono_table,pc),a3
bra 2f
1: movea.l (a3)+,a1
bsr stricmp
beq 20f
2: move.l (a3)+,d2
bne 1b
moveq.l #SS16B,d6
lea.l (str_dot_stereo_table,pc),a3
bra 2f
1: movea.l (a3)+,a1
bsr stricmp
beq 20f
2: move.l (a3)+,d2
bne 1b
;拡張子.pcm
moveq.l #ADPCM,d6
move.l #15625,d2
lea.l (str_dot_pcm,pc),a1
bsr stricmp
beq 20f
;拡張子.fmpはCDXAチェックをスキップする(CD-ROMドライブの特殊な操作をなるべく避けるため)
lea.l (str_dot_fmp,pc),a1
bsr stricmp
beq 10f
;CDXAファイルは_READできないので,ヘッダをチェックする前にCDXAかどうか調べる必要がある
movea.l a4,a0
bsr is_cdxa_file ;CDXAのチェック
bmi 10f
st.b (pb_is_cdxa,a2)
move.l d0,(pb_cdxa_start,a2)
move.l d1,(pb_cdxa_length,a2)
bra 98f
10: move.w fileno,d0
bsr fmp_check ;FMPフォーマットのチェック
bmi 10f ;FMPフォーマットではない
bne 84f ;未対応のFMPデータ
move.l d2,d0
bsr frequency_to_timerd_count
bmi 84f
move.b d0,data_timerd_count
moveq.l #SFMP,d6
subq.l #1,d1
bne 20f
moveq.l #MFMP,d6
bra 20f
10: move.w fileno,d0
bsr wave_check ;WAVEフォーマットのチェック
bmi 10f ;WAVEフォーマットではない
bne 83f ;未対応のWAVEデータ
moveq.l #SS16L,d6
subq.l #1,d1
bne 20f
moveq.l #MS16L,d6
bra 20f
10: move.w fileno,d0
bsr aiff_check ;AIFFフォーマットのチェック
bmi 10f ;AIFFフォーマットではない
bne 85f ;未対応のAIFFデータ
moveq.l #SS16B,d6
subq.l #1,d1
bne 20f
moveq.l #MS16B,d6
bra 20f
10: move.w fileno,-(sp)
DOS _CLOSE
addq.l #2,sp
move.w #-1,fileno
bra 82f ;フォーマットが不明
20: move.w d6,data_format ;データのフォーマット
move.l d2,data_frequency ;データのサンプリング周波数
movea.l current_param_ptr,a0
cmpi.l #$80000000,(pb_trktop,a0)
bne 86f
cmpi.l #$7FFFFFFF,(pb_trkbtm,a0)
bne 86f
cmpi.l #$80000000,(pb_idxtop,a0)
bne 86f
cmpi.l #$7FFFFFFF,(pb_idxbtm,a0)
bne 86f
cmpi.l #1,(pb_rangetype,a0)
bne 1f
;<ofs>の場合
cmpi.l #$80000000,(pb_top,a0)
bgt @f
clr.l (pb_top,a0)
@@: cmpi.l #$7FFFFFFF,(pb_btm,a0)
blt @f
move.l d4,(pb_btm,a0)
@@:
tst.l (pb_top,a0)
blt 87f
cmp.l (pb_btm,a0),d4
blt 87f
move.w #1,-(sp)
move.l (pb_top,a0),-(sp)
move.w fileno,-(sp)
DOS _SEEK
addq.l #8,sp
tst.l d0
bmi 87f
move.l (pb_btm,a0),d4
sub.l (pb_top,a0),d4
bra 2f
1:
;<msf>の場合
2:
and.b #$FE,d4 ;データのサイズを偶数にする
move.l d4,filesize ;データのサイズ
move.l d4,restsize ;データの残りサイズ
tst.b silent_flag
bne 1f
bsr 71f
lea.l (m_open_file_1,pc),a0
tst.b conv_flag
beq @f
lea.l (m_open_file_2,pc),a0
@@: bsr eprintcrlf
1:
.if 0
move.w fileno,-(sp)
bsr is68000
bne 1f
DOS $FF7C ;_GET_FCB_ADR,V2にもある
bra 2f
1: DOS $FFAC ;_GET_FCB_ADR
2: addq.l #2,sp
movea.l d0,a1
bsr super
tst.b (1,a1)
bmi 81f ;キャラクタデバイス
movea.l (2,a1),a1 ;内部DPBテーブル
tst.w (10,a1)
beq 1f ;特殊デバイス
move.b (26,a1),d0 ;メディアバイト
cmp.b #$F0,d0
blo 2f
cmp.b #$F7,d0
bhi 2f
1: st.b file_scsi_flag
bra 3f
2: sf.b file_scsi_flag
3: bsr user
.endif
98: moveq.l #1,d0 ;データあり
99: movem.l (sp)+,d1-d7/a0-a6
rts
86: move.w #EXIT_ILLEGAL_RANGE,exit_code
bsr 70f
lea.l (m_file_illegal_range,pc),a0
bra 89f
87: move.w #EXIT_OUT_OF_RANGE,exit_code
bsr 70f
lea.l (m_file_out_of_range,pc),a0
bra 89f
80: move.w #EXIT_FILE_NOT_FOUND,exit_code
bsr 70f
lea.l (m_file_not_found,pc),a0
bra 89f
82: move.w #EXIT_UNKNOWN_FORMAT,exit_code
bsr 70f
lea.l (m_unknown_format,pc),a0
bra 89f
83: move.w #EXIT_UNKNOWN_WAVE,exit_code
bsr 70f
lea.l (m_unknown_wave,pc),a0
bra 89f
84: move.w #EXIT_UNKNOWN_FMP,exit_code
bsr 70f
lea.l (m_unknown_fmp,pc),a0
bra 89f
85: move.w #EXIT_UNKNOWN_AIFF,exit_code
bsr 70f
lea.l (m_unknown_aiff,pc),a0
.if 0
bra 89f
81: bsr user
lea.l (m_character_device,pc),a0
.endif
89: bsr eprintcrlf
90: moveq.l #-1,d0
bra 99b
70: bsr eaonly
71: lea.l (m_stdin_message,pc),a0
cmpi.b #'-',(a4)
bne @f
tst.b (1,a4)
beq eprint
@@: lea.l (m_file_message1,pc),a0
bsr eprint
movea.l a4,a0
bsr eprint
lea.l (m_file_message2,pc),a0
bra eprint
.align 4
str_dot_mono_table:
.dc.l 16000,str_dot_m16
.dc.l 18900,str_dot_m19
.dc.l 22050,str_dot_m22
.dc.l 24000,str_dot_m24
.dc.l 32000,str_dot_m32
.dc.l 37800,str_dot_m38
.dc.l 44100,str_dot_m44
.dc.l 48000,str_dot_m48
.dc.l 15625,str_dot_p16
.dc.l 0
.align 4
str_dot_stereo_table:
.dc.l 16000,str_dot_s16
.dc.l 18900,str_dot_s19
.dc.l 22050,str_dot_s22
.dc.l 24000,str_dot_s24
.dc.l 32000,str_dot_s32
.dc.l 37800,str_dot_s38
.dc.l 44100,str_dot_s44
.dc.l 48000,str_dot_s48
.dc.l 0
str_dot_m16: .dc.b '.m16',0
str_dot_m19: .dc.b '.m19',0
str_dot_m22: .dc.b '.m22',0
str_dot_m24: .dc.b '.m24',0
str_dot_m32: .dc.b '.m32',0
str_dot_m38: .dc.b '.m38',0
str_dot_m44: .dc.b '.m44',0
str_dot_m48: .dc.b '.m48',0
str_dot_s16: .dc.b '.s16',0
str_dot_s19: .dc.b '.s19',0
str_dot_s22: .dc.b '.s22',0
str_dot_s24: .dc.b '.s24',0
str_dot_s32: .dc.b '.s32',0
str_dot_s38: .dc.b '.s38',0
str_dot_s44: .dc.b '.s44',0
str_dot_s48: .dc.b '.s48',0
str_dot_pcm: .dc.b '.pcm',0
str_dot_p16: .dc.b '.p16',0
str_dot_fmp: .dc.b '.fmp',0
m_stdin_message: .dc.b '標準入力',0
m_file_message1:: .dc.b "ファイル `",0
m_file_message2:: .dc.b "' ",0
m_open_file_1: .dc.b 'を再生します',0
m_open_file_2: .dc.b 'を変換します',0
m_file_illegal_range: .dc.b 'の再生範囲が間違っています',0
m_file_out_of_range: .dc.b 'の再生範囲が範囲外です',0
m_file_not_found: .dc.b 'が見つかりません',0
m_unknown_format: .dc.b 'のデータの種類が不明です',0
m_unknown_wave: .dc.b 'は未対応の WAVE データです',0
m_unknown_fmp: .dc.b 'は未対応の FMP データです',0
m_unknown_aiff: .dc.b 'は未対応の AIFF データです',0
.if 0
m_character_device: .dc.b 'キャラクタデバイスでは処理できません',0
.endif
.even
.data
.even
fileno: .dc.w -1
.bss
.if 0
file_scsi_flag: .ds.b 1
.endif
.align 4
filesize: .ds.l 1 ;データのサイズ
restsize: .ds.l 1 ;データの残りサイズ
.bss
.align 4
filename_nameptr: .ds.l 1
filename_buffer: .ds.b 92
.even
files_buffer: .ds.b fiSize
;----------------------------------------------------------------
;ファイルを読み込む
;<a0.l:出力バッファの先頭
;<a1.l:入力バッファの先頭
;>d0.l:データのサイズ,-1=エラー
.text
.align 4,$2048
read_file::
movem.l d1-d7/a0-a6,-(sp)
cmpi.w #SFMP,data_format
beq 1f
cmpi.w #MFMP,data_format
beq 1f
move.l a0,d7 ;バッファのアドレス
movea.l a1,a6 ;開始アドレス
movea.l a1,a2 ;開始アドレス
bra 2f
1:
;FMPフォーマットの場合は出力バッファに読み込む
move.l a0,d7 ;バッファのアドレス
movea.l a0,a6 ;開始アドレス
movea.l a0,a2 ;開始アドレス
2:
.if TEST_68000=0
IS68000 d0
bne @f
.endif
tst.b wave_data_flag
beq @f
addq.l #1,a2 ;68000でlittle-endianのとき
@@:
move.l restsize,d0 ;データの残りのサイズ
beq 99f
move.l bufhsiz,d5 ;バッファのサイズ
move.b read_shift_count,d1
lsr.l d1,d5
cmp.l d5,d0
bls @f
move.l d5,d0
@@:
tst.b xx_data_flag
beq @f
and.l #-16,d0
beq 99f
@@:
sub.l d0,restsize
movea.l d0,a5 ;今回の転送バイト数
10: move.l stpsiz,d5
cmp.l a5,d5
bls @f
move.l a5,d5
@@: suba.l d5,a5 ;残りバイト数
move.l d5,-(sp)
move.l a2,-(sp)
move.w fileno,-(sp)
bsr scsi_hard_soft_on
move.w #EXIT_BREAK,exit_code
DOS _READ
clr.w exit_code
bsr scsi_hard_soft_off
lea.l (10,sp),sp
tst.l d0
bmi 80f
adda.l d0,a2 ;次回のアドレス
cmp.l d5,d0
beq @f
clr.l restsize ;読み出せなければ中止(エラーなし)
bra 11f
@@:
.if CURRENT_TIME=0
moveq.l #'.',d0
bsr silent_eputchar
.endif
tst.b esc_aborted
bne 90f
move.l a5,d0 ;残りバイト数
bne 10b
11:
;68000のとき必要ならばmovepを使ったエンディアン変換を行う
.if TEST_68000=0
IS68000 d0
bne @f
.endif
tst.b wave_data_flag
beq @f
subq.l #1,a2 ;68000でlittle-endianのとき
move.l a2,d0
sub.l a6,d0
movea.l a6,a0
bsr convert_endian_68000
@@:
movea.l d7,a0 ;出力バッファの先頭
movea.l a6,a1 ;入力データの先頭
* movea.l a2,a2 ;入力データの末尾+1
movea.l preconv_routine,a6 ;PCMデータをOPMのTLの並びに変換する
jsr (a6)
move.l a0,d0 ;出力データの末尾+1
sub.l a1,d0 ;出力データの長さ
beq 99f
tas.b (-1,a0) ;エンドコードを付加する
smi.b d1
neg.b d1
sf.b (a0)
move.b d1,(1,a0) ;0,1(末尾のデータのbit7の値)
move.l a1,nxttop
tst.l d0
99: movem.l (sp)+,d1-d7/a0-a6
rts
80: move.w #EXIT_FILE_READ_ERROR,exit_code
lea.l (m_read_file_error,pc),a0
bsr eprintcrlf
90: moveq.l #-1,d0
bra 99b
m_read_file_error: .dc.b 13,10
.dc.b '読み込みエラー',0
;----------------------------------------------------------------
;ファイルをクローズする
.text
.align 4,$2048
close_file::
move.w fileno,d0
ble @f ;オープンしていないまたは標準入力
move.w d0,-(sp)
DOS _CLOSE
addq.l #2,sp
move.w #-1,fileno
@@: moveq.l #0,d0
rts
;----------------------------------------------------------------
;入力データの残りバイト数を得る
;>d0.l:データの残りバイト数
.text
.align 4,$2048
get_restsize_file::
move.l restsize,d0
rts
;----------------------------------------------------------------
;AIFFヘッダの解析
;<d0.w:ファイルハンドル(チェックを開始する位置をシークしてあること)
;>d0.l:0=AIFFファイル,-1=AIFFファイルではない,1=未対応のAIFFファイル
;>d1.l:チャンネル数(1=モノラル,2=ステレオ)
;>d2.l:サンプリング周波数(44100など)
;>d3.l:ビット数(8=符号なし8ビット,16=符号つき16ビット),現在は16のみ
;>d4.l:データ本体のサイズ
;>z-flag:eq=AIFFファイル,ne=AIFFファイルではない/未対応のAIFFファイル
;>n-flag:pl=AIFFファイル,mi=AIFFファイルではない
;>シーク位置:(eq)データの先頭位置,(ne)変化しない
.text
.align 4,$2048
aiff_check:
movem.l d1-d4/d7/a0-a4,-(sp) ;AIFFファイルならばd1-d4は捨てられる
;ヘッダのバッファを確保する
lea.l (-(AIFF_CHECK_LENGTH+4),sp),sp
move.w d0,d7 ;ファイルハンドル
;ヘッダのバッファを初期化しておく
movea.l sp,a0
move.w #(AIFF_CHECK_LENGTH+4)/2-1,d0
@@: clr.w (a0)+
dbra d0,@b
;ヘッダを読み込む
movea.l sp,a2
movea.l sp,a4 ;エラー処理用に必要
pea.l AIFF_CHECK_LENGTH.w
move.l a2,-(sp)
move.w d7,-(sp)
DOS _READ
lea.l (10,sp),sp
tst.l d0
bmi 90f
lea.l (a2,d0.l),a4 ;読み込んだヘッダの末尾+1
cmp.l #(4+4)+(4)+(4+4+2+4+2+2+2)+(4+4+8),d0
;最低でも(4+4)+(4)+(4+4+2+4+2+2+2)+(4+4+8)=48バイト以上必要
blo 90f
;ヘッダの検索
lea.l (str_FORM,pc),a1
movea.l a2,a0
moveq.l #4,d0
bsr strncmp
bne 90f
addq.l #4+4,a2
1: lea.l (str_AIFF,pc),a1
movea.l a2,a0
moveq.l #4,d0
bsr strncmp
beq 2f
addq.l #1,a2
cmpa.l a4,a2
blo 1b
bra 90f ;AIFFヘッダが見つからない
2:
addq.l #4,a2
1: lea.l (str_COMM,pc),a1
movea.l a2,a0
moveq.l #4,d0
bsr strncmp
beq 2f
addq.l #1,a2
cmpa.l a4,a2
blo 1b
bra 90f ;COMMヘッダが見つからない
2:
lea.l (4+4+2+4+2+2+2,a2),a0 ;COMMヘッダは全部で4+4+2+4+2+2+2=20バイト以上必要
cmpa.l a0,a4
blo 90f ;COMMヘッダの末尾まで読めていない
lea.l (4,a2),a0 ;length
bsr getmem_long_big
cmp.l #2+4+2+2+2,d0
blo 90f ;COMMヘッダが短すぎる
lea.l (4+4,a2,d0.l),a3 ;COMMヘッダの末尾
cmpa.l a3,a4
blo 90f ;SSNDヘッダが読み込めていない
1: lea.l (str_SSND,pc),a1
movea.l a3,a0
moveq.l #4,d0
bsr strncmp
beq 2f
addq.l #1,a3
cmpa.l a4,a3
blo 1b
bra 90f ;SSNDヘッダが見つからない
2: lea.l (4+4+8,a3),a0 ;SSNDヘッダは全部で4+4+8=16バイト
cmpa.l a0,a4
blo 90f ;SSNDヘッダの末尾まで読めていない
;COMMヘッダの確認
lea.l (4+4,a2),a0
bsr getmem_word_big
move.l d0,d1 ;1=mono,2=stereo
beq 91f
subq.l #3,d0
bcc 91f
lea.l (4+4+2,a2),a0 ;length
bsr getmem_long_big
move.l d0,d4
beq 91f ;データの長さが0
lea.l (4+4+2+4,a2),a0
bsr getmem_word_big
move.l d0,d3 ;1データのビット数
cmp.l #16,d0
bne 91f
lea.l (4+4+2+4+2+2,a2),a0
bsr getmem_word_big
move.l d0,d2 ;サンプリング周波数
cmp.l #1,d1 ;1=mono,2=stereo
bne 1f
cmp.l #MIN_FREQUENCY_MONO,d2
blo 91f
cmp.l #MAX_FREQUENCY_MONO,d2
bhi 91f
bra 2f
1: cmp.l #MIN_FREQUENCY_STEREO,d2
blo 91f
cmp.l #MAX_FREQUENCY_STEREO,d2
bhi 91f
2:
add.l d4,d4 ;8ビットのとき1倍,16ビットのとき2倍
lsl.l d1,d4 ;モノラルのとき1倍,ステレオのとき2倍
;データのバイトサイズ
;データの先頭をシークする
lea.l (4+4+8,a3),a0 ;データの先頭
suba.l a4,a0 ;現在位置からデータの先頭までのオフセット(負数)
move.w #1,-(sp) ;現在位置から
move.l a0,-(sp)
move.w d7,-(sp)
DOS _SEEK
addq.l #8,sp
lea.l (AIFF_CHECK_LENGTH+4,sp),sp
moveq.l #0,d0
lea.l (4*4,sp),sp ;元のd1-d4を捨てる
99: movem.l (sp)+,d7/a0-a4
rts
90: moveq.l #-1,d0 ;AIFFファイルではない
bra 97f
91: moveq.l #1,d0 ;未対応のAIFFファイル
97: move.l d0,d1
movea.l sp,a0 ;開始位置
suba.l a4,a0 ;現在位置から開始位置までのオフセット(正数)
move.w #1,-(sp) ;現在位置から
move.l a0,-(sp)
move.w d7,-(sp)
DOS _SEEK
addq.l #8,sp
move.l d1,d0
lea.l (AIFF_CHECK_LENGTH+4,sp),sp
movem.l (sp)+,d1-d4 ;元の値を復元する
bra 99b
str_FORM: .dc.b 'FORM'
str_AIFF: .dc.b 'AIFF'
str_COMM: .dc.b 'COMM'
str_SSND: .dc.b 'SSND'
.even
;----------------------------------------------------------------
; FMPファイルの構造
; 第1識別子(ファイルの種類を表す)
; .dc.b 'FMP '
; 以降はセパレータ($1A)まで任意の文字列
; 通常は,1行目をプログラムのヘッダ,2行目をコマンドラインとする
; セーブしたプログラムの名称とバージョン(m_banner)
; .dc.b PROGNAME,'.X'
; .dc.b ' <<Stereo PCM player with built-in OPM>> '
; .dc.b 'v',VERSION,' (',DATE,') by M.Kamada',13,10
; セーブ方法(セーブ時の環境変数とコマンドラインをそのまま記録)
; .dc.b 'set S44PLAY=-force',13,10
; .dc.b 'set CDROM=6',13,10
; .dc.b 'A:\BIN\s44play.x 1 -c track1.fmp',13,10
; セパレータ
; .dc.b $1A
; 第2識別子(以下の構造を表す)
; .dc.l 'S44P'
; .dc.l FMP_VERSION
; ヘッダのサイズ
; .dc.l 4+4 ;データ本体のサイズ以降を含まない
; ヘッダ
; チャンネル数(1=モノラル,2=ステレオ)
; .dc.l 2
; サンプリング周波数(44100)
; .dc.l 44100
; (バージョンが上がったときは,新しい項目をここに挿入する)
; データ本体のサイズ
; .dc.l ?
; データ本体
; .dc.b ~
;----------------------------------------------------------------
;FMPヘッダの解析
;<d0.w:ファイルハンドル(チェックを開始する位置をシークしてあること)
;>d0.l:0=FMPファイル,-1=FMPファイルではない,1=未対応のFMPファイル
;>d1.l:チャンネル数(1=モノラル,2=ステレオ)
;>d2.l:サンプリング周波数(44100など)
;>d3.l:ビット数,16のみ
;>d4.l:データ本体のサイズ
;>z-flag:eq=FMPファイル,ne=FMPファイルではない/未対応のFMPファイル
;>n-flag:pl=FMPファイル,mi=FMPファイルではない
;>シーク位置:(eq)データの先頭位置,(ne)変化しない
.text
.align 4,$2048
fmp_check:
movem.l d1-d4/d6-d7/a0/a2/a4,-(sp) ;FMPファイルならばd1-d4は捨てられる
;ヘッダのバッファを確保する
lea.l (-(FMP_CHECK_LENGTH+4),sp),sp
move.w d0,d7 ;ファイルハンドル
;ヘッダのバッファを初期化しておく
movea.l sp,a0
move.w #(FMP_CHECK_LENGTH+4)/2-1,d0
@@: clr.w (a0)+
dbra d0,@b
;ヘッダを読み込む
movea.l sp,a0
movea.l sp,a4 ;エラー処理用に必要
pea.l FMP_CHECK_LENGTH.w
move.l a0,-(sp)
move.w d7,-(sp)
DOS _READ
lea.l (10,sp),sp
tst.l d0
bmi 90f
lea.l (a0,d0.l),a4 ;読み込んだヘッダの末尾+1
cmp.l #4+1,d0 ;最低でも4+1=5バイト以上必要
blo 90f
;'FMP 'を確認
bsr getmem_long_big
cmp.l #'FMP ',d0
bne 90f ;'FMP 'で始まっていない
;<a0.l:'FMP 'の直後
;$1Aまでスキップする
move.l a4,d1
sub.w a0,d1 ;5バイト以上読み込んであるので1以上になる
moveq.l #$1A,d0
subq.w #1,d1
1: cmp.b (a0)+,d0
dbeq d1,1b
bne 90f ;$1Aがない
;<a0.l:$1Aの直後
;'S44P'を確認
bsr getmem_long_big
cmp.l #'S44P',d0
bne 90f ;'S44P'でない
;<a0.l:'S44P'の直後
;バージョンを確認
bsr getmem_long_big
cmpa.l a4,a0
bcc 90f
cmp.l #'0.77',d0 ;FMPファイルはVERSION='0.77'から
blo 90f
cmp.l #'9.99',d0 ;念のため先頭が数字であることを確認しておく
bhi 90f
cmp.l #FMP_VERSION,d0 ;自分よりも新しいヘッダは解釈できない
bhi 91f
move.l d0,d6 ;バージョン
;<a0.l:バージョンの直後
;ヘッダのサイズを確認
bsr getmem_long_big
cmpa.l a4,a0
bcc 90f
cmp.l #FMP_CHECK_LENGTH,d0 ;ヘッダの末尾の位置が手前になってしまわないようにする
bcc 90f
lea.l (4,a0,d0.l),a2 ;ヘッダの末尾+4=データ本体のサイズの直後
cmpa.l a4,a2 ;データの直前まで読み込めていなければエラー
bhi 90f
;チャンネル数
bsr getmem_long_big
tst.l d0
beq 91f
cmp.l #2,d0
bhi 91f
move.l d0,d1 ;チャンネル数(1=モノラル,2=ステレオ)
;サンプリング周波数
bsr getmem_long_big
move.l d0,d2 ;サンプリング周波数
;ビット数
moveq.l #16,d3
;データ本体のサイズ
lea.l (-4,a2),a0
bsr getmem_long_big
move.l d0,d4 ;データ本体のサイズ
;データの先頭をシークする
; movea.l a2,a0 ;データの先頭
suba.l a4,a0 ;現在位置からデータの先頭までのオフセット(負数)
move.w #1,-(sp) ;現在位置から
move.l a0,-(sp)
move.w d7,-(sp)
DOS _SEEK
addq.l #8,sp
lea.l (FMP_CHECK_LENGTH+4,sp),sp
moveq.l #0,d0
lea.l (4*4,sp),sp ;元のd1-d4を捨てる
99: movem.l (sp)+,d6-d7/a0/a2/a4
rts
90: moveq.l #-1,d0 ;FMPファイルではない
bra 97f
91: moveq.l #1,d0 ;未対応のFMPファイル
97: move.l d0,d1
movea.l sp,a0 ;開始位置
suba.l a4,a0 ;現在位置から開始位置までのオフセット(正数)
move.w #1,-(sp) ;現在位置から
move.l a0,-(sp)
move.w d7,-(sp)
DOS _SEEK
addq.l #8,sp
move.l d1,d0
lea.l (FMP_CHECK_LENGTH+4,sp),sp
movem.l (sp)+,d1-d4 ;元の値を復元する
bra 99b
;----------------------------------------------------------------
;WAVEヘッダの解析
;<d0.w:ファイルハンドル(チェックを開始する位置をシークしてあること)
;>d0.l:0=WAVEファイル,-1=WAVEファイルではない,1=未対応のWAVEファイル
;>d1.l:チャンネル数(1=モノラル,2=ステレオ)
;>d2.l:サンプリング周波数(44100など)
;>d3.l:ビット数(8=符号なし8ビット,16=符号つき16ビット),現在は16のみ
;>d4.l:データ本体のサイズ
;>z-flag:eq=WAVEファイル,ne=WAVEファイルではない/未対応のWAVEファイル
;>n-flag:pl=WAVEファイル,mi=WAVEファイルではない
;>シーク位置:(eq)データの先頭位置,(ne)変化しない
.text
.align 4,$2048
wave_check:
movem.l d1-d4/d7/a0-a4,-(sp) ;WAVEファイルならばd1-d4は捨てられる
;ヘッダのバッファを確保する
lea.l (-(WAVE_CHECK_LENGTH+4),sp),sp
move.w d0,d7 ;ファイルハンドル
;ヘッダのバッファを初期化しておく
movea.l sp,a0
move.w #(WAVE_CHECK_LENGTH+4)/2-1,d0
@@: clr.w (a0)+
dbra d0,@b
;ヘッダを読み込む
movea.l sp,a2
movea.l sp,a4 ;エラー処理用に必要
pea.l WAVE_CHECK_LENGTH.w
move.l a2,-(sp)
move.w d7,-(sp)
DOS _READ
lea.l (10,sp),sp
tst.l d0
bmi 90f
lea.l (a2,d0.l),a4 ;読み込んだヘッダの末尾+1
cmp.l #(4+4+16)+(4+4),d0 ;最低でも(4+4+16)+(4+4)=32バイト以上必要
blo 90f
;ヘッダの検索
lea.l (str_riff,pc),a1
movea.l a2,a0
moveq.l #4,d0
bsr strncmp
bne 90f
1: lea.l (str_fmt,pc),a1
movea.l a2,a0
moveq.l #3,d0
bsr strncmp
beq 2f
addq.l #1,a2
cmpa.l a4,a2
blo 1b
bra 90f ;fmtヘッダが見つからない
2: lea.l (4+4+16,a2),a0 ;fmtヘッダは全部で4+4+16=24バイト以上必要
cmpa.l a0,a4
blo 90f ;fmtヘッダの末尾まで読めていない
lea.l (4,a2),a0 ;length
bsr getmem_long_little
cmp.l #16,d0
blo 90f ;fmtヘッダが短すぎる
lea.l (a2,d0.l),a3 ;fmtヘッダの末尾
cmpa.l a3,a4
blo 90f ;dataヘッダが読み込めていない
1: lea.l (str_data,pc),a1
movea.l a3,a0
moveq.l #4,d0
bsr strncmp
beq 2f
addq.l #1,a3
cmpa.l a4,a3
blo 1b
bra 90f ;dataヘッダが見つからない
2: lea.l (4+4,a3),a0 ;dataヘッダは全部で4+4=8バイト以上必要
cmpa.l a0,a4
blo 90f ;dataヘッダの末尾まで読めていない
;fmtヘッダの確認
lea.l (8,a2),a0 ;compressed
bsr getmem_word_little
subq.l #1,d0
bne 91f ;非圧縮でない
lea.l (10,a2),a0
bsr getmem_word_little
move.l d0,d1 ;1=mono,2=stereo
beq 91f
subq.l #3,d0
bcc 91f
lea.l (12,a2),a0
bsr getmem_long_little
move.l d0,d2 ;サンプリング周波数
cmp.l #1,d1 ;1=mono,2=stereo
bne 1f
cmp.l #MIN_FREQUENCY_MONO,d2
blo 91f
cmp.l #MAX_FREQUENCY_MONO,d2
bhi 91f
bra 2f
1: cmp.l #MIN_FREQUENCY_STEREO,d2
blo 91f
cmp.l #MAX_FREQUENCY_STEREO,d2
bhi 91f
2:
lea.l (22,a2),a0
bsr getmem_word_little
move.l d0,d3 ;1データのビット数
cmp.l #16,d0
bne 91f
;dataヘッダの確認
lea.l (4,a3),a0 ;length
bsr getmem_long_little
move.l d0,d4
beq 91f ;データの長さが0
;データの先頭をシークする
lea.l (8,a3),a0 ;データの先頭
suba.l a4,a0 ;現在位置からデータの先頭までのオフセット(負数)
move.w #1,-(sp) ;現在位置から
move.l a0,-(sp)
move.w d7,-(sp)
DOS _SEEK
addq.l #8,sp
lea.l (WAVE_CHECK_LENGTH+4,sp),sp
moveq.l #0,d0
lea.l (4*4,sp),sp ;元のd1-d4を捨てる
99: movem.l (sp)+,d7/a0-a4
rts
90: moveq.l #-1,d0 ;WAVEファイルではない
bra 97f
91: moveq.l #1,d0 ;未対応のWAVEファイル
97: move.l d0,d1
movea.l sp,a0 ;開始位置
suba.l a4,a0 ;現在位置から開始位置までのオフセット(正数)
move.w #1,-(sp) ;現在位置から
move.l a0,-(sp)
move.w d7,-(sp)
DOS _SEEK
addq.l #8,sp
move.l d1,d0
lea.l (WAVE_CHECK_LENGTH+4,sp),sp
movem.l (sp)+,d1-d4 ;元の値を復元する
bra 99b
str_riff: .dc.b 'RIFF'
str_fmt: .dc.b 'fmt'
str_data: .dc.b 'data'
.even
;----------------------------------------------------------------
;メモリからbig-endianの16ビットのデータを取り出す
;<a0.l:アドレス
;>d0.l:データ
;>a0.l:データの直後のアドレス
.text
.align 4,$2048
getmem_word_big:
moveq.l #0,d0
move.b (a0)+,d0
lsl.w #8,d0
move.b (a0)+,d0
rts
;----------------------------------------------------------------
;メモリからbig-endianの32ビットのデータを取り出す
;<a0.l:アドレス
;>d0.l:データ
;>a0.l:データの直後のアドレス
.text
.align 4,$2048
getmem_long_big:
move.b (a0)+,d0
lsl.w #8,d0
move.b (a0)+,d0
swap.w d0
move.b (a0)+,d0
lsl.w #8,d0
move.b (a0)+,d0
rts
;----------------------------------------------------------------
;メモリからlittle-endianの16ビットのデータを取り出す
;<a0.l:アドレス
;>d0.l:データ
;>a0.l:データの直後のアドレス
.text
.align 4,$2048
getmem_word_little:
moveq.l #0,d0
move.b (a0)+,d0
ror.w #8,d0
move.b (a0)+,d0
ror.w #8,d0
rts
;----------------------------------------------------------------
;メモリからlittle-endianの32ビットのデータを取り出す
;<a0.l:アドレス
;>d0.l:データ
;>a0.l:データの直後のアドレス
.text
.align 4,$2048
getmem_long_little:
move.b (a0)+,d0
ror.l #8,d0
move.b (a0)+,d0
ror.l #8,d0
move.b (a0)+,d0
ror.l #8,d0
move.b (a0)+,d0
ror.l #8,d0
rts